
module ConsoleInterlocutor (performConversation) where
import IO --hiding ( catch )
import Char
import qualified StringHelper
import qualified FilmManager
import qualified ClientManager
import qualified IdObject
import qualified Film
import qualified Client
import qualified Loan
import qualified LoanManager
import qualified Date
import DBS
--import qualified Control.Exception as E
--import Prelude hiding ( catch )
--import Control.Exception


performConversation :: DBS -> IO DBS
performConversation db = do putStrLn "Aby wyswietlic liste polecen wpisz 'help', aby wyjsc 'exit'"
                            db1 <- converse db
                            putStrLn "Do widzenia"
                            return db1

converse :: DBS -> IO DBS
converse db = do putStr "MovieRent> "
                 command <- getLine
                 case takeWhile (isAlpha) command of
                   "exit" -> return db
                   "help" -> do menuDisp
                                converse db
                   "movie" -> catch( do
                                 db1 <- movieMngMenu (dropWhile (isSpace) (drop 5 command)) db
                                 converse db1) (\e -> do 
                                        putStrLn "Wykonanie polecenia zakonczone niepowodzeniem"
                                        converse db)
                   "client"-> catch( do
                                 db1 <- clientMngMenu (dropWhile (isSpace) (drop 6 command)) db
                                 converse db1) (\e -> do 
                                        putStrLn "Wykonanie polecenia zakonczone niepowodzeniem"
                                        converse db)
                   "loan" -> catch( do
                                 db1 <- loanMngMenu (dropWhile (isSpace) (drop 4 command)) db
                                 converse db1) (\e -> do 
                                        putStrLn "Wykonanie polecenia zakonczone niepowodzeniem"
                                        converse db)
                   "showMovies" -> catch( do 
				 showMovies (dropWhile (isSpace) (drop 10 command)) db
				 converse db) (\e -> do
                                        putStrLn "Wykonanie polecenia zakonczone niepowodzeniem"
					converse db)
                   "showLoans" -> do 
                                     showLoans (dropWhile (isSpace) (drop 9 command)) db
                                     converse db
                   "top" -> do showTop (dropWhile (isSpace) (drop 3 command)) db
                               converse db
                   _ -> do putStrLn "Niewlasciwe polecenie"
                           converse db
                
menuDisp :: IO ()
menuDisp = do putStrLn (
                "\nMenu glowne - wybierz polecenie:\n" ++
                "-------------------------------------------------\n" ++
                "\t movie - Komendy dla zarzadzania filmami\n" ++
                "\t client - Komendy dla zarzadzania wypozyczajacymi\n" ++
                "\t loan - Komendy dla zarzadzania wypozyczeniami\n" ++
                "\t showMovies [stan] - Aktualny stan dostepnosci/wypozyczen filmow, 1=dost,2=wyp,3=zagub\n" ++
                "\t\t (mozesz podac kilka na raz, bez spacji, lub zadnego - wtedy wyswietlone zostana wszystkie filmy)\n" ++
                "\t showLoans [data od] [data do] - Zestawienie wypozyczen i zwrotow dla danego okresu\n" ++
                "\t top [data od] [data do] [wielkosc] - Ranking popularnosci filmow dla danego okresu (ilosc wypozyczen)\n" ++
                "\t\t gdzie [wielkosc] to ilosc wyswietlanych wynikow (jesli nie podana to domyslnie przyjmowane 10)\n" ++
                "\t\t jesli [data od] [data do] nie zostana podane przyjmowany jest okres ostatnich 30 dni\n" ++ 
                "\t\t - w tym przypadku [wielkosc] takze mozna podac lub nie\n" ++ 
                "\t exit - Wyjdz z programu")
              return()

movieMngMenu :: [Char] -> DBS -> IO DBS
movieMngMenu str db = case takeWhile (isAlpha) str of
                     [] -> do  putStrLn (
                                 "\nMenu 'Filmy' - wybierz polecenie:\n" ++
                                 "-------------------------------------------------\n" ++
                                 "\t movie add [tytul] [rok produkcji] [rezyser] [gatunek] [krotki opis] - dodaj film, zwraca id dodanego filmu\n" ++
                                 "\t movie del [id filmu] - usun film\n" ++
                                 "\t movie find [fragment pola tytul, rezyser lub opis] - znajdz film, zwraca id filmu\n" ++
                                 "\t movie edit [id filmu] [pole] [wartosc] - zmien dane filmu, gdzie [pole] to 1 dla pola 'tytul',\n" ++ 
                                 "\t\t2 dla 'rok produkcji', 3 dla 'rezyser', 4 dla 'gatunek', 5 dla stanu filmu (1=dost,2=wyp,3=zagub) ,\n" ++ 
                                 "\t\t6 dla 'krotki opis' a [wartosc] to nowa wartosc\n" ++
                                 "  uwaga: napisy skadajace sie z wiecej niz jednego slowa wprowadzaj pomiedzy znakami \" i \"")
                               return db
                     "add" -> callAddFunc str db
                     "del" -> callDelFunc str db
                     "find" -> do films <- callFindFunc str db
                                  putStrLn ("Znaleziono filmy: \n" ++
                                        StringHelper.displayInTable (
                                                ["Id", "Tytul", "Rok produkcji", "Rezyser", 
                                                "Gatunek", "Dostepnosc", "Opis"] : 
                                                (map (IdObject.toList) films)) )
                                  return db
                     "edit" -> callEditFunc str db
                     _ -> do putStrLn "Niewlasciwe polecenie"
                             return db

callAddFunc :: String -> DBS -> IO DBS
callAddFunc str db = 
     if length args == 5 then
        case maybeArg1 of 
           Nothing   -> do
                   putStrLn ("Niewlasciwa typ argumentu: rok produkcji musi byc liczba")
                   return db
           Just arg1 -> do
                   let db1 = FilmManager.insertFilm ((args !! 0), arg1, (args !! 2), (args !! 3), Film.Available, (args !! 4)) db
                   putStrLn ("Operacja wykonana poprawnie")
                   return db1
     else
        do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
           return db
       where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 3 str)))
             maybeArg1 = StringHelper.string2int (args !! 1)

callDelFunc :: String -> DBS -> IO DBS
callDelFunc str db = 
        if length args == 1 then
                case maybeArg0 of  
                   Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator filmu musi byc liczba")
                                   return db
                   Just arg0 ->
                        case (FilmManager.deleteFilm arg0 db) of			
				Left db1  -> do 
                                       		putStrLn ("Operacja wykonana poprawnie")
                                        	return db1
                                Right msg -> do 
                                		putStrLn ("Nie udalo sie usunac filmu poniewaz " ++ msg)
                                        	return db                        
        else
                do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                   return db
               where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 3 str)))
                     maybeArg0 = StringHelper.string2int (args !! 0)

callFindFunc :: String -> DBS -> IO [Film.Film]
callFindFunc str db = if length args == 1 then
                        do return (FilmManager.searchFilm (args !! 0) db)
                     else
                        do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                           return []
                       where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 4 str)))

callEditFunc :: String -> DBS -> IO DBS
callEditFunc str db = 
        if length args == 3 then
                case maybeArg0 of 
                  Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator filmu musi byc liczba")
                                  return db
                  Just arg0 ->
                    case maybeArg1 of 
                      Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: numer pola musi byc liczba")
                                      return db
                      Just arg1 -> 
                        case (FilmManager.updateFilm arg0 db arg1 (args !! 2)) of
        		  Left db1  -> do 
                               		putStrLn ("Operacja wykonana poprawnie")
                                	return db1
                          Right msg -> do 
                        		putStrLn ("Nie udalo sie zmienic filmu poniewaz " ++ msg)
                                	return db
        else
                do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                   return db
               where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 4 str)))
                     maybeArg0 = StringHelper.string2int (args !! 0)
                     maybeArg1 = StringHelper.string2int (args !! 1)

clientMngMenu :: [Char] -> DBS -> IO DBS
clientMngMenu str db = case takeWhile (isAlpha) str of
                     [] -> do  putStrLn (
                                 "\nMenu 'Klienci' - wybierz polecenie:\n" ++
                                 "-------------------------------------------------\n" ++
                                 "\t client add [imie] [nazwisko] [data ur.] [adres] - dodaj klienta\n" ++
                                 "\t client del [id klienta] - usun klienta\n" ++
                                 "\t client find [fragment pola imie, nazwisko, data ur. lub adres] - znajdz klienta, zwraca liste klientow\n" ++
                                 "\t client edit [id klienta] [pole] [wartosc] - zmien dane klienta, gdzie [pole] to 1 dla pola 'imie',\n" ++ 
                                 "\t\t2 dla 'nazwisko', 3 dla 'data ur.', 4 dla 'adres', a [wartosc] to nowa wartosc\n" ++
                                 "  uwaga: napisy skladajace sie z wiecej niz jednego slowa wprowadzaj pomiedzy znakami \" i \"")
                               return db
                     "add" -> callAddClientFunc str db
                     "del" -> callDelClientFunc str db
                     "find" -> do clients <- callFindClientFunc str db
                                  putStrLn ("Znaleziono klientow: \n" ++
                                        StringHelper.displayInTable (
                                                ["Id", "Imie", "Nazwisko", "Data urodzenia", "Adres zamieszkania"]
                                                : (map (IdObject.toList) clients)) )
                                  return db
                     "edit" -> callEditClientFunc str db
                     _ -> do putStrLn "Niewlasciwe polecenie"
                             return db

callAddClientFunc :: String -> DBS -> IO DBS
callAddClientFunc str db = 
     if length args == 4 then do
           let db1 = (ClientManager.insertClient ((args !! 0), (args !! 1), (args !! 2), (args !! 3)) db)
	   putStrLn ("Operacja wykonana pomyslnie")
           return db1 
     else do
           putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
           return db
       where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 3 str)))

callDelClientFunc :: String -> DBS -> IO DBS
callDelClientFunc str db = 
        if length args == 1 then
                case maybeArg0 of 
                        Nothing   -> 
                                do putStrLn ("Niewlasciwa typ argumentu: identyfikator klienta musi byc liczba")
                                   return db
                        Just arg0 -> 
                          case (ClientManager.deleteClient arg0 db) of
                               Left db1  -> do
                                     putStrLn ("Operacja wykonana pomyslnie")
                                     return db1
                               Right msg -> do
                                     putStrLn ("Nie udalo sie usunac klienta poniewaz " ++ msg)
                                     return db
        else
                do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                   return db
               where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 3 str)))
                     maybeArg0 = StringHelper.string2int (args !! 0)

callFindClientFunc :: String -> DBS -> IO [Client.Client]
callFindClientFunc str db = if length args == 1 then
                        do return (ClientManager.searchClient (args !! 0) db)
                     else
                        do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                           return []
                       where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 4 str)))

callEditClientFunc :: String -> DBS -> IO DBS
callEditClientFunc str db = 
        if length args == 3 then
                case maybeArg0 of 
                  Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator klienta musi byc liczba")
                                  return db
                  Just arg0 ->
                    case maybeArg1 of 
                      Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: numer pola musi byc liczba")
                                      return db
                      Just arg1 -> 
                          case (ClientManager.updateClient arg0 db arg1 (args !! 2)) of
                               Left db1  -> do
                                     putStrLn ("Operacja wykonana pomyslnie")
                                     return db1
                               Right msg -> do
                                     putStrLn ("Nie udalo sie zmodyfikowac klienta poniewaz " ++ msg)
                                     return db
        else
                do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                   return db
               where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 4 str)))
                     maybeArg0 = StringHelper.string2int (args !! 0)
                     maybeArg1 = StringHelper.string2int (args !! 1)

loanMngMenu :: [Char] -> DBS -> IO DBS
loanMngMenu str db = case takeWhile (isAlpha) str of
                     [] -> do  putStrLn (
                                 "\nMenu 'Wypozyczenia' - wybierz polecenie:\n" ++
                                 "-------------------------------------------------\n" ++
                                 "\t loan add [id klienta] [id filmu] [data wypozyczenia] [data do zwrotu] - dodaj wypozyczenie\n" ++
                                 "\t loan ret [id filmu] [data zwrotu] - zwraca wypozyczenie\n" ++
                                 "\t loan edit [id klienta] [id filmu] [pole] [wartosc] - zmien dane wypozyczenia, gdzie [pole] to\n" ++ 
                                 "\t\t 1 dla 'data wypozyczenia', 2 dla 'data do zwrotu',\n" ++ 
                                 "  uwaga: kazda date wprowadzaj pomiedzy znakami \" i \" i w formacie:\n" ++
                                 "         dzien{spacja}miesiac{spacja}rok np: \"12 02 2010\"\n" ++
                                 "         (pomiedzy znakami \" i \" uzyj tylko liczb arabskich i spacji)")
                               return db
                     "add" -> callAddLoanFunc str db
		     "ret" -> callRetLoanFunc str db
                     "edit" -> callEditLoanFunc str db
                     _ -> do putStrLn "Niewlasciwe polecenie"
                             return db

callAddLoanFunc :: String -> DBS -> IO DBS
callAddLoanFunc str db = 
        if length args == 4 then
                case maybeArg0 of 
                  Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator klienta musi byc liczba")
                                  return db
                  Just arg0 ->
                    case maybeArg1 of 
                      Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator filmu musi byc liczba")
                                      return db
                      Just arg1 -> 
                        case maybeDate1 of
                          Just date1 -> case maybeDate2 of
                                Just date2 -> case maybeDb of
                                        Left db1   -> do 
                                                putStrLn ("Operacja wykonana poprawnie")
                                                return db1
                                        Right msg  -> do 
                                                putStrLn ("Nie udalo sie dodac wypozyczenia poniewaz " ++ msg)
                                                return db
                                      where maybeDb = LoanManager.insertLoan arg0 arg1 date1 date2 db
                                _          -> do 
                                        putStrLn ("Zly format daty 'data do zwrotu' - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                                        return db
                          _          -> do 
                                putStrLn ("Zly format daty 'data wypozyczenia' - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                                return db
        else
                do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                   return db
            where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 3 str)))
                  maybeDate1 = Date.constructFromString (args !! 2)
                  maybeDate2 = Date.constructFromString (args !! 3)
                  maybeArg0 = StringHelper.string2int (args !! 0)
                  maybeArg1 = StringHelper.string2int (args !! 1)

callRetLoanFunc :: String -> DBS -> IO DBS
callRetLoanFunc str db = 
        if length args == 2 then
                case maybeArg0 of 
                  Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator filmu musi byc liczba")
                                  return db
                  Just arg0 ->
                    case maybeDate of
                        Just date -> case maybeDb of
                                Left db1   -> do 
                                        putStrLn ("Operacja wykonana poprawnie")
                                        return db1
                                Right msg  -> do 
                                      putStrLn ("Nie udalo sie zakonczyc wypozyczenia poniewaz " ++ msg)
                                      return db
                                where maybeDb = LoanManager.returnLoan arg0 date db
                        _          -> do 
                                        putStrLn ("Zly format daty 'data zwrotu' - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                                        return db                               
        else
                do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                   return db
            where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 3 str)))
                  maybeDate = Date.constructFromString (args !! 1)
                  maybeArg0 = StringHelper.string2int (args !! 0)

callEditLoanFunc :: String -> DBS -> IO DBS
callEditLoanFunc str db = 
        if length args == 4 then
                case maybeArg0 of 
                  Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator klienta musi byc liczba")
                                  return db
                  Just arg0 ->
                    case maybeArg1 of 
                      Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: identyfikator filmu musi byc liczba")
                                      return db
                      Just arg1 -> 
                        case maybeArg2 of 
                          Nothing   -> do putStrLn ("Niewlasciwa typ argumentu: numer pola musi byc liczba")
                                          return db
                          Just arg2 -> 
                            case maybeDate1 of
                              Just date1 -> do 
                        	case (LoanManager.updateLoan arg0 arg1 arg2 date1 db) of
					Left db1 -> do 
                                	       		putStrLn ("Operacja wykonana poprawnie")
                                	        	return db1
                                	Right msg-> do 
                                      			putStrLn ("Nie udalo sie dodac wypozyczenia poniewaz " ++ msg)
                                      			return db
                              _          -> do 
                                        putStrLn ("Zly format daty - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                                        return db
        else
                do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                   return db
            where args = StringHelper.getWords (words (dropWhile (isSpace) (drop 4 str)))
                  maybeDate1 = Date.constructFromString (args !! 3)
                  maybeArg0 = StringHelper.string2int (args !! 0)
                  maybeArg1 = StringHelper.string2int (args !! 1)
                  maybeArg2 = StringHelper.string2int (args !! 2)

showMovies :: [Char] -> DBS -> IO DBS
showMovies str db = 
        if length args == 1 then
           if (Nothing `elem` maybeI) then do              
                putStrLn ("Niewlasciwa typ argumentu: stan musi byc liczba")
                return db
           else if (foldr (||) False (map (\x -> x < 0 || x > 2) i)) then do              
                        putStrLn ("Stan, ktory podales nie jest prawidlowy")
                        return db
                else do
                        let searchStates = (map (toEnum) i)::[Film.State]
                            films = DBS.selectFilmBy ((`elem` searchStates) . (Film.getState)) db
                        putStrLn ("Znaleziono filmy:\n" ++
                                StringHelper.displayInTable (
                                ["Id", "Tytul", "Rok produkcji", "Rezyser", 
                                "Gatunek", "Dostepnosc", "Opis"] : 
                                (map (IdObject.toList) films)) )
                        return db
        else if length args == 0 then do
                let searchStates = (map (toEnum) [0,1,2])::[Film.State]
                    films = DBS.selectFilmBy ((`elem` searchStates) . (Film.getState)) db
                putStrLn ("Wszystkie filmy:\n" ++
                        StringHelper.displayInTable (
                        ["Id", "Tytul", "Rok produkcji", "Rezyser", 
                        "Gatunek", "Dostepnosc", "Opis"] : 
                        (map (IdObject.toList) films)) )
                return db
        else do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                return db
            where args = StringHelper.getWords (words (dropWhile (isSpace) str))
                  maybeI = map ((fmap (\x -> x-1)) . (StringHelper.string2int) . (:"")) (args !! 0)
                  i = map (\x -> case x of 
                                    Nothing -> -1
                                    Just y  -> y) maybeI

showLoans :: [Char] -> DBS -> IO DBS
showLoans str db = 
        if length args == 2 then
                case maybeDate1 of
                  Nothing       -> do
                        putStrLn ("Zly format daty 'od' - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                        return db
                  Just dateFrom -> 
                        case maybeDate2 of
                          Nothing     -> do
                                putStrLn ("Zly format daty 'do' - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                                return db
                          Just dateTo ->
                                case (LoanManager.getByPeriod dateFrom dateTo db) of
                                  Right errMessage      -> do
                                        putStrLn errMessage
                                        return db
                                  Left loansWithInfoStr -> do
                                        putStrLn ("Wypozyczenia z podanego okresu:\n" ++
                                                StringHelper.displayInTable (
                                                ["Id wyp.", "Id filmu", "Tytul", "Rok produkcji", "Data wypozyczenia",
                                                "Data 'do zwrotu'", "Data zwrotu", "Imie klienta", "Nazwisko klienta"] :
                                                (map (convertToDisplayForm) loansWithInfoStr)) )
                                        return db
        else do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                return db
            where args = StringHelper.getWords (words (dropWhile (isSpace) str))
                  maybeDate1 = Date.constructFromString (args !! 0)
                  maybeDate2 = Date.constructFromString (args !! 1)

convertToDisplayForm :: (Loan.Loan, (Film.Film, Client.Client)) -> [String]
convertToDisplayForm loanData = 
        [(show (IdObject.getId loan)), (show (IdObject.getId film)), (Film.getTitle film), (show (Film.getYear film)), 
        (Date.display (Loan.getDateLoaned loan)), (Date.display (Loan.getDateObliged loan)), 
        (Date.display (Loan.getDateReturned loan)), (Client.getName client), (Client.getSurname client)]
        where loan = fst loanData
              film = fst (snd loanData)
              client = snd (snd loanData)

showTop :: [Char] -> DBS -> IO DBS
showTop str db = 
        if (length args >= 0 && length args <= 3) then
           case maybeTopSize of 
              Nothing      -> do putStrLn ("Niewlasciwa typ argumentu: wielkosc zestawienia 'top' musi byc liczba")
                                 return db
              Just topSize -> do
                maybeDate1 <- iomaybeDate1
                maybeDate2 <- iomaybeDate2
                db1 <- (callTop maybeDate1 maybeDate2 topSize db)
                return db1
        else do putStrLn ("Niewlasciwa liczba argumentow (" ++ show(length args) ++ ") dla tego polecenia")
                return db
            where args = StringHelper.getWords (words (dropWhile (isSpace) str))
                  iomaybeDate1 = if (length args /= 2) && (length args /= 3) 
                                 then Date.getActualDateMinus 1
                                 else return (Date.constructFromString (args !! 0))
                  iomaybeDate2 = if (length args /= 2) && (length args /= 3) 
                                 then Date.getActualDateMinus 0
                                 else return (Date.constructFromString (args !! 1))
                  maybeTopSize = if (length args < 3) && (length args /= 1) 
                                 then Just 10
                                 else if (length args == 1) then
                                        StringHelper.string2int (args !! 0)
                                      else 
                                        StringHelper.string2int (args !! 2)

callTop :: Maybe Date.Date -> Maybe Date.Date -> Int -> DBS -> IO DBS
callTop maybeDate1 maybeDate2 topSize db = 
        case maybeDate1 of
          Nothing       -> do
                putStrLn ("Zly format daty 'od' - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                return db
          Just dateFrom -> 
                case maybeDate2 of
                  Nothing     -> do
                        putStrLn ("Zly format daty 'do' - podaj date w formacie: \"dzien{spacja}miesiac{spacja}rok\" uzywajac tylko cyfr arabskich")
                        return db
                  Just dateTo ->
                        case (LoanManager.getTop dateFrom dateTo topSize db) of
                          Right errMessage      -> do
                                putStrLn errMessage
                                return db
                          Left topInfo -> do
                                putStrLn ("Najczesciej wypozyczane ksiazki z podanego okresu:\n" ++
                                        StringHelper.displayInTable (
                                        ["Tytul", "Rok produkcji", "Rezyser",
                                        "Gatunek", "Liczba wypozyczen"] :
                                        (map (convertTopToDisplayForm) topInfo)) )
                                return db


convertTopToDisplayForm :: LoanManager.FilmTop -> [String]
convertTopToDisplayForm (LoanManager.FilmTop film loansNum) = 
        [(Film.getTitle film), (show (Film.getYear film)), 
        (Film.getDirector film), (Film.getKind film), 
        (show loansNum)]
